package com.skyd.core.android.game;

import java.util.ArrayList;

import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;

import com.skyd.core.math.MathEx;
import com.skyd.core.vector.Vector2DF;
import com.skyd.core.vector.VectorRect2DF;

/**
 * 游戏中可见对象的基类
 * 
 * @author SkyD
 * 
 */
public abstract class GameObject {

	/**
	 * 初始值为new Vector2DF(0,0)。 功能注释：在屏幕上显示的坐标位置
	 */
	private Vector2DF _Position = new Vector2DF(0, 0);

	/**
	 * 获取Position。 功能注释：在屏幕上显示的坐标位置
	 * 
	 * @return 当前的Vector2DF类型的值
	 */
	public Vector2DF getPosition() {
		return _Position;
	}

	/**
	 * 设置Position。 功能注释：在屏幕上显示的坐标位置
	 * 
	 * @param value
	 *            要设置的Vector2DF类型值
	 */
	public void setPosition(Vector2DF value) {
		_Position = value;
	}

	/**
	 * 设置Position为其默认值(new Vector2DF(0,0))。 功能注释：在屏幕上显示的坐标位置
	 */
	public void setPositionToDefault() {
		setPosition(new Vector2DF(0, 0));
	}

	/**
	 * 初始值为new Vector2DF(0,0)。 功能注释：显示坐标位置偏移量
	 */
	private Vector2DF _PositionOffset = new Vector2DF(0, 0);

	/**
	 * 获取PositionOffset。 功能注释：显示坐标位置偏移量
	 * 
	 * @return 当前的Vector2DF类型的值
	 */
	public Vector2DF getPositionOffset() {
		return _PositionOffset;
	}

	/**
	 * 设置PositionOffset。 功能注释：显示坐标位置偏移量
	 * 
	 * @param value
	 *            要设置的Vector2DF类型值
	 */
	public void setPositionOffset(Vector2DF value) {
		_PositionOffset = value;
	}

	/**
	 * 设置PositionOffset为其默认值(new Vector2DF(0,0))。 功能注释：显示坐标位置偏移量
	 */
	public void setPositionOffsetToDefault() {
		setPositionOffset(new Vector2DF(0, 0));
	}

	/**
	 * 初始值为new Vector2DF(-1,-1)。
	 * 功能注释：在X、Y两个方向上的尺寸，如果为-1则自动以其内容为准。叶节点应有确切值，根节点作为容器，均不允许使用-1。
	 */
	private Vector2DF _Size = new Vector2DF(-1, -1);

	/**
	 * 获取Size。 功能注释：在X、Y两个方向上的尺寸，如果为-1则自动以其内容为准。叶节点应有确切值，根节点作为容器，均不允许使用-1。
	 * 
	 * @return 当前的Vector2DF类型的值
	 */
	public Vector2DF getSize() {
		return _Size;
	}

	/**
	 * 设置Size。 功能注释：在X、Y两个方向上的尺寸，如果为-1则自动以其内容为准。叶节点应有确切值，根节点作为容器，均不允许使用-1。
	 * 
	 * @param value
	 *            要设置的Vector2DF类型值
	 */
	public void setSize(Vector2DF value) {
		_Size = value;
	}

	/**
	 * 设置Size为其默认值(new Vector2DF(-1,-1))。
	 * 功能注释：在X、Y两个方向上的尺寸，如果为-1则自动以其内容为准。叶节点应有确切值，根节点作为容器，均不允许使用-1。
	 */
	public void setSizeToDefault() {
		setSize(new Vector2DF(-1, -1));
	}

	/**
	 * 初始值为false。 功能注释：指示当指定了宽度和高度时，是否强制拉伸内容为指定的尺寸，如果为false则会保持纵横比缩放内容
	 */
	private boolean _IsStretchContent = false;

	/**
	 * 获取IsStretchContent。 功能注释：指示当指定了宽度和高度时，是否强制拉伸内容为指定的尺寸，如果为false则会保持纵横比缩放内容
	 * 
	 * @return 当前的boolean类型的值
	 */
	public boolean getIsStretchContent() {
		return _IsStretchContent;
	}

	/**
	 * 设置IsStretchContent。 功能注释：指示当指定了宽度和高度时，是否强制拉伸内容为指定的尺寸，如果为false则会保持纵横比缩放内容
	 * 
	 * @param value
	 *            要设置的boolean类型值
	 */
	public void setIsStretchContent(boolean value) {
		_IsStretchContent = value;
	}

	/**
	 * 设置IsStretchContent为其默认值(false)。
	 * 功能注释：指示当指定了宽度和高度时，是否强制拉伸内容为指定的尺寸，如果为false则会保持纵横比缩放内容
	 */
	public void setIsStretchContentToDefault() {
		setIsStretchContent(false);
	}

	/**
	 * 初始值为false。 功能注释：指示是否在不同分辨率下仍保持绝对相同的显示尺寸，若为false，则会根据显示区域基准尺寸做相应比例的调整
	 */
	private boolean _IsUseAbsoluteSize = false;

	/**
	 * 获取IsUseAbsoluteSize。
	 * 功能注释：指示是否在不同分辨率下仍保持绝对相同的显示尺寸，若为false，则会根据显示区域基准尺寸做相应比例的调整
	 * 
	 * @return 当前的boolean类型的值
	 */
	public boolean getIsUseAbsoluteSize() {
		return _IsUseAbsoluteSize;
	}

	/**
	 * 设置IsUseAbsoluteSize。
	 * 功能注释：指示是否在不同分辨率下仍保持绝对相同的显示尺寸，若为false，则会根据显示区域基准尺寸做相应比例的调整
	 * 
	 * @param value
	 *            要设置的boolean类型值
	 */
	public void setIsUseAbsoluteSize(boolean value) {
		_IsUseAbsoluteSize = value;
	}

	/**
	 * 设置IsUseAbsoluteSize为其默认值(false)。
	 * 功能注释：指示是否在不同分辨率下仍保持绝对相同的显示尺寸，若为false，则会根据显示区域基准尺寸做相应比例的调整
	 */
	public void setIsUseAbsoluteSizeToDefault() {
		setIsUseAbsoluteSize(false);
	}

	/**
	 * 初始值为false。 功能注释：指示是否在不同分辨率下仍保持绝对相同的显示位置，若为false，则会根据显示区域基准尺寸做相应比例的调整
	 */
	private boolean _IsUseAbsolutePosition = false;

	/**
	 * 获取IsUseAbsolutePosition。
	 * 功能注释：指示是否在不同分辨率下仍保持绝对相同的显示位置，若为false，则会根据显示区域基准尺寸做相应比例的调整
	 * 
	 * @return 当前的boolean类型的值
	 */
	public boolean getIsUseAbsolutePosition() {
		return _IsUseAbsolutePosition;
	}

	/**
	 * 设置IsUseAbsolutePosition。
	 * 功能注释：指示是否在不同分辨率下仍保持绝对相同的显示位置，若为false，则会根据显示区域基准尺寸做相应比例的调整
	 * 
	 * @param value
	 *            要设置的boolean类型值
	 */
	public void setIsUseAbsolutePosition(boolean value) {
		_IsUseAbsolutePosition = value;
	}

	/**
	 * 设置IsUseAbsolutePosition为其默认值(false)。
	 * 功能注释：指示是否在不同分辨率下仍保持绝对相同的显示位置，若为false， 则会根据显示区域基准尺寸做相应比例的调整
	 */
	public void setIsUseAbsolutePositionToDefault() {
		setIsUseAbsolutePosition(false);
	}

	/**
	 * 初始值为new Vector2DF(1f,1f)。 功能注释：X轴向和Y轴向的缩放比例，1为100%
	 */
	private Vector2DF _Scale = new Vector2DF(1f, 1f);

	/**
	 * 获取Scale。 功能注释：X轴向和Y轴向的缩放比例，1为100%
	 * 
	 * @return 当前的Vector2DF类型的值
	 */
	public Vector2DF getScale() {
		return _Scale;
	}

	/**
	 * 设置Scale。 功能注释：X轴向和Y轴向的缩放比例，1为100%
	 * 
	 * @param value
	 *            要设置的Vector2DF类型值
	 */
	public void setScale(Vector2DF value) {
		_Scale = value;
	}

	/**
	 * 设置Scale为其默认值(new Vector2DF(1f,1f))。 功能注释：X轴向和Y轴向的缩放比例，1为100%
	 */
	public void setScaleToDefault() {
		setScale(new Vector2DF(1f, 1f));
	}

	/**
	 * 初始值为0。 功能注释：旋转角度
	 */
	private float _Rotation = 0;

	/**
	 * 获取Rotation。 功能注释：旋转角度
	 * 
	 * @return 当前的float类型的值
	 */
	public float getRotation() {
		return _Rotation;
	}

	/**
	 * 设置Rotation。 功能注释：旋转角度
	 * 
	 * @param value
	 *            要设置的float类型值
	 */
	public void setRotation(float value) {
		_Rotation = value;
	}

	/**
	 * 设置Rotation为其默认值(0)。 功能注释：旋转角度
	 */
	public void setRotationToDefault() {
		setRotation(0);
	}

	/**
	 * 初始值为1。 功能注释：不透明度，1为100%
	 */
	private float _Opacity = 1;

	/**
	 * 获取Opacity。 功能注释：不透明度，1为100%
	 * 
	 * @return 当前的float类型的值
	 */
	public float getOpacity() {
		return _Opacity;
	}

	/**
	 * 设置Opacity。 功能注释：不透明度，1为100%
	 * 
	 * @param value
	 *            要设置的float类型值
	 */
	public void setOpacity(float value) {
		_Opacity = value;
		if (_Opacity > 1)
			_Opacity = 1;
		else if (_Opacity < 0)
			_Opacity = 0;
	}

	/**
	 * 设置Opacity为其默认值(1)。 功能注释：不透明度，1为100%
	 */
	public void setOpacityToDefault() {
		setOpacity(1);
	}

	/**
	 * 可见性
	 */
	private boolean _Visible = true;

	/**
	 * 可见性，此值受其父对象递归影响，父对象中有任意一个为false，那么此对象也为false
	 * 
	 * @return 当前的boolean类型的值
	 */
	public boolean getDisplayVisible() {
		if (getParent() == null)
			return _Visible;
		else
			return _Visible && getParent().getDisplayVisible();
	}

	/**
	 * 可见性，此对象的实际可见性值，此处获取的值不受其父对象影响
	 * 
	 * @return 当前的boolean类型的值
	 */
	public boolean getVisibleOriginalValue() {
		return _Visible;
	}

	/**
	 * 可见性
	 * 
	 * @param value
	 *            要设置的boolean类型值
	 */
	protected void setVisible(boolean value) {
		_Visible = value;
	}

	/**
	 * 显示。执行之后如果其包含显示内容子对象，那么将递归设置所有子对象为显示状态。
	 */
	public void show() {
		this.setVisible(true);
		if (this.getDisplayContentChild() != null)
			this.getDisplayContentChild().show();
	}

	/**
	 * 隐藏。执行之后如果其包含显示内容子对象，那么将递归设置所有子对象为隐藏状态。
	 */
	public void hide() {
		this.setVisible(false);
		if (this.getDisplayContentChild() != null)
			this.getDisplayContentChild().hide();
	}

	/**
	 * 初始值为null。 功能注释：父对象
	 */
	private GameObject _Parent = null;

	/**
	 * 获取Parent。 功能注释：父对象
	 * 
	 * @return 当前的GameObject类型的值
	 */
	public GameObject getParent() {
		return _Parent;
	}

	/**
	 * 设置Parent。 功能注释：父对象
	 * 
	 * @param value
	 *            要设置的GameObject类型值
	 * @throws GameException
	 *             设置父对象时发生的异常
	 */
	public void setParent(GameObject value) throws GameException {
		_Parent = value;
	}

	/**
	 * 设置Parent为其默认值(null)。 功能注释：父对象
	 * 
	 * @throws GameException
	 *             设置父对象时发生的异常
	 */
	public void setParentToDefault() throws GameException {
		setParent(null);
	}

	/**
	 * 获取其显示内容子对象，这个对象决定了它的显示内容尺寸，用于需要根据内容调整当前对象的尺寸时使用。叶节点没有子项，而根节点作为画布使用，
	 * 其尺寸不受内容影响，故它们的此均属性无效。
	 * 
	 * @return 子对象
	 */
	public abstract GameObject getDisplayContentChild();

	/**
	 * 获取映射后的显示位置
	 * @param m 自定映射矩阵
	 * 
	 * @return 显示位置
	 */
	public Vector2DF getDisplayPosition(Matrix m) {
//		Vector2DF v = getDrawPosition();
//		v.plus(getDrawPositionOffset());
//		if (getParent() != null)
//			v.plus(getParent().getDisplayPosition());
//		return v;
		return getDisplayAngularPointA(getMatrix());
	}
	
	/**
	 * 获取当前实际显示位置
	 * @return 显示位置
	 */
	public Vector2DF getDisplayPosition()
	{
		return getDisplayPosition(getMatrix());
	}

	// /**
	// * 获取经过偏移量叠加计算后的显示位置，该值为原始值，在当前节点未经缩放处理
	// *
	// * @return 经过偏移量叠加计算后的显示位置
	// */
	// public Vector2DF getDisplayPositionOriginalValue() {
	// if (getParent() != null)
	// return getParent().getDisplayPosition().plusNew(getPosition())
	// .plusNew(getPositionOffset());
	// return getPosition().plusNew(getPositionOffset());
	// }

	/**
	 * 获取映射后的显示尺寸
	 * @param m 自定映射矩阵
	 * 
	 * @return 显示尺寸
	 */
	public Vector2DF getDisplaySize(Matrix m) {
//		Vector2DF v = getDrawSize();
//		Vector2DF sc = getDisplayScale();
//		v.scale(sc.getX(), sc.getY());
//		return v;
		Vector2DF a = getDisplayAngularPointA(m);
		Vector2DF b = getDisplayAngularPointB(m);
		Vector2DF c = getDisplayAngularPointB(m);
		return new Vector2DF(Math.abs(b.minus(a).getLength()),Math.abs(c.minus(a).getLength()));
	}
	
	/**
	 * 获取当前实际显示尺寸
	 * 
	 * @return 当前实际显示尺寸
	 */
	public Vector2DF getDisplaySize() {
		return getDisplaySize(getMatrix());
	}

	// /**
	// * 获取经过计算后的显示尺寸，该值为原始值，在当前节点未经缩放处理
	// *
	// * @return 经过计算后的显示尺寸
	// */
	// public Vector2DF getDisplaySizeOriginalValue() {
	// if (this.getDisplayContentChild() != null) {
	// Vector2DF size = this.getDisplayContentChild().getDisplaySize();
	// if (_IsStretchContent) {
	// if (getSize().getX() >= 0)
	// size.setX(getSize().getX());
	// if (getSize().getY() >= 0)
	// size.setY(getSize().getY());
	// } else {
	// size = DrawHelper.calculateScaleSize(size.getX(), size.getY(),
	// getSize().getX() >= 0 ? getSize().getX() : size.getX(),
	// getSize().getY() >= 0 ? getSize().getY() : size.getY(),
	// true);
	// }
	// return size;
	// } else {
	// return getSize().getClone();
	// }
	// }

	/**
	 * 获取映射后的显示区域
	 * @param m 自定映射矩阵
	 * 
	 * @return 显示区域
	 */
	public Rect getDisplayRect(Matrix m) {
//		Vector2DF p = getDisplayPosition();
//		Vector2DF s = getDisplaySize();
//		s.plus(p);
//		return new Rect((int) Math.ceil(p.getX()), (int) Math.ceil(p.getY()),
//				(int) Math.ceil(s.getX()), (int) Math.ceil(s.getY()));
		Vector2DF a = getDisplayAngularPointA(m);
		Vector2DF b = getDisplayAngularPointB(m);
		Vector2DF c = getDisplayAngularPointC(m);
		Vector2DF d = getDisplayAngularPointD(m);
		float left = MathEx.min(a.getX(),b.getX(),c.getX(),d.getX());
		float right = MathEx.max(a.getX(),b.getX(),c.getX(),d.getX());
		float top = MathEx.min(a.getY(),b.getY(),c.getY(),d.getY());
		float bottom = MathEx.max(a.getY(),b.getY(),c.getY(),d.getY());
		return new Rect((int)left, (int)top, (int)right, (int)bottom);
	}
	
	/**
	 * 获取显示区域
	 * 
	 * @return 显示区域
	 */
	public Rect getDisplayRect() {
		return getDisplayRect(getMatrix());
	}
	
	/**
	 * 获取映射后的显示区域
	 * @param m 自定映射矩阵
	 * 
	 * @return 显示区域
	 */
	public RectF getDisplayRectF(Matrix m) {
//		Vector2DF p = getDisplayPosition();
//		Vector2DF s = getDisplaySize();
//		s.plus(p);
//		return new RectF(p.getX(), p.getY(),
//				s.getX(), s.getY());
		Vector2DF a = getDisplayAngularPointA(m);
		Vector2DF b = getDisplayAngularPointB(m);
		Vector2DF c = getDisplayAngularPointC(m);
		Vector2DF d = getDisplayAngularPointD(m);
		Float left = MathEx.min(a.getX(),b.getX(),c.getX(),d.getX());
		Float right = MathEx.max(a.getX(),b.getX(),c.getX(),d.getX());
		Float top = MathEx.min(a.getY(),b.getY(),c.getY(),d.getY());
		Float bottom = MathEx.max(a.getY(),b.getY(),c.getY(),d.getY());
		return new RectF(left, top, right, bottom);
	}
	
	/**
	 * 获取显示区域
	 * 
	 * @return 显示区域
	 */
	public RectF getDisplayRectF() {
		return getDisplayRectF(getMatrix());
	}
	
	/**
	 * 获取映射后的显示区域
	 * @param m 自定映射矩阵
	 * 
	 * @return 显示区域
	 */
	public VectorRect2DF getDisplayVectorRect2DF(Matrix m) {
//		Vector2DF p = getDisplayPosition();
//		Vector2DF s = getDisplaySize();
//		s.plus(p);
//		return new VectorRect2DF(p.getX(), p.getY(),
//				s.getX(), s.getY());
		Vector2DF a = getDisplayAngularPointA(m);
		Vector2DF b = getDisplayAngularPointB(m);
		Vector2DF c = getDisplayAngularPointC(m);
		Vector2DF d = getDisplayAngularPointD(m);
		Float left = MathEx.min(a.getX(),b.getX(),c.getX(),d.getX());
		Float right = MathEx.max(a.getX(),b.getX(),c.getX(),d.getX());
		Float top = MathEx.min(a.getY(),b.getY(),c.getY(),d.getY());
		Float bottom = MathEx.max(a.getY(),b.getY(),c.getY(),d.getY());
		return new VectorRect2DF(left, top, right, bottom);
	}
	
	/**
	 * 获取显示区域
	 * 
	 * @return 显示区域
	 */
	public VectorRect2DF getDisplayVectorRect2DF() {
		return getDisplayVectorRect2DF(getMatrix());
	}

	// /**
	// * 获取显示区域，该值为原始值，在当前节点未经缩放处理
	// *
	// * @return 显示区域
	// */
	// public Rect getDisplayRectOriginalValue() {
	// Vector2DF p = getDisplayPositionOriginalValue();
	// Vector2DF s = getDisplaySizeOriginalValue();
	// s.plus(p);
	// return new Rect((int) Math.ceil(p.getX()), (int) Math.ceil(p.getY()),
	// (int) Math.ceil(s.getX()), (int) Math.ceil(s.getY()));
	// }

	/**
	 * 获取映射后的显示旋转角度
	 *  @param m 自定映射矩阵
	 *  
	 * @return 显示的旋转角度
	 */
	public float getDisplayRotation(Matrix m) {
//		if (getParent() != null)
//			return getParent().getDisplayRotation() + getRotation();
//		return getRotation();
		Vector2DF a = getDisplayAngularPointA(m);
		Vector2DF b = getDisplayAngularPointB(m);
		return b.minus(a).getAngle();
	}
	
	/**
	 * 获取显示的旋转角度
	 * 
	 * @return 显示的旋转角度
	 */
	public float getDisplayRotation() {
		return getDisplayRotation(getMatrix());
	}

	/**
	 * 获取显示的不透明度
	 * 
	 * @return 显示的不透明度
	 */
	public float getDisplayOpacity() {
		if (getParent() != null)
			return getParent().getDisplayOpacity() * getOpacity();
		return getOpacity();
	}

	/**
	 * 获取映射后的显示缩放比例
	 *  @param m 自定映射矩阵
	 * @return 显示的缩放比例
	 */
	public Vector2DF getDisplayScale(Matrix m) {
//		Vector2DF v = getScale().getClone();
//		if (getParent() == null || getParent() instanceof GameScene)
//			return v;
//		float xs = getParent().getDrawWidth() / getDrawWidth();
//		float ys = getParent().getDrawHeight() / getDrawHeight();
//		if (getParent().getIsStretchContent()) {
//			v.scale(xs, ys);
//		} else {
//			float as = Math.min(xs, ys);
//			v.scale(as, as);
//		}
//		Vector2DF pv = getParent().getDisplayScale();
//		v.scale(pv.getX(), pv.getY());
//		return v;
		Vector2DF v = getDisplaySize(m);
		return new Vector2DF(v.getX()/getDrawSize().getX(),v.getY()/getDrawSize().getY());
	}
	
	/**
	 * 获取显示的缩放比例
	 * 
	 * @return 显示的缩放比例
	 */
	public Vector2DF getDisplayScale() {
		return getDisplayScale(getMatrix());
	}

	/**
	 * 获取显示位置的分辨率修正缩放比例
	 * 
	 * @return 显示位置的分辨率修正缩放比例
	 */
	public Vector2DF getDisplayAreaFixScaleForPosition() {
		if (_IsUseAbsolutePosition)
			return new Vector2DF(1, 1);
		return getRoot().getDisplayAreaFixScaleReferenceValue();
	}

	/**
	 * 获取显示尺寸的分辨率修正缩放比例
	 * 
	 * @return 显示尺寸的分辨率修正缩放比例
	 */
	public Vector2DF getDisplayAreaFixScaleForSize() {
		if (_IsUseAbsoluteSize)
			return new Vector2DF(1, 1);
		return getRoot().getDisplayAreaFixScaleReferenceValue();
	}

	/**
	 * 绘制操作，当对象不可见时则忽略此操作
	 * 
	 * @param c
	 *            画板
	 * @param drawArea
	 *            绘图参考区域
	 */
	public void draw(Canvas c, Rect drawArea) {
		if (getDisplayVisible())
		{
			c.save();
			operateCanvas(c);
			if (onDrawing(c, drawArea)) {
				drawChilds(c, drawArea);
				drawSelf(c, drawArea);
			}
			onDrawn(c, drawArea);
			c.restore();
		}
		else onSkipDraw(c,drawArea);
	}

	/**
	 * 当不需要绘制时触发，子类可以重写此方法以实现额外操作，比如释放图像
	 * @param c 画板
	 * @param drawArea 绘图参考区域
	 */
	protected void onSkipDraw(Canvas c, Rect drawArea) {
		
	}

	/**
	 * 获取绘图时应绘制的尺寸
	 * 
	 * @return 绘图时应绘制的尺寸
	 */
	public Vector2DF getDrawSize() {
		Vector2DF sc = getDisplayAreaFixScaleForSize();
		Vector2DF v = new Vector2DF(getDrawWidth(), getDrawHeight());
		v.scale(sc.getX(), sc.getY());
		return v;
	}

	/**
	 * 获取绘图时应绘制的宽度，如果自身值为-1，则向其子类寻求此值
	 * 
	 * @return 绘图时应绘制的宽度
	 */
	public float getDrawWidth() {
		float v = getSize().getX();
		if (v < 0)
			v = getDisplayContentChild().getDrawWidth();
		return v;
	}

	/**
	 * 获取绘图时应绘制的高度，如果自身值为-1，则向其子类寻求此值
	 * 
	 * @return 绘图时应绘制的高度
	 */
	public float getDrawHeight() {
		float v = getSize().getY();
		if (v < 0)
			v = getDisplayContentChild().getDrawHeight();
		return v;
	}

	/**
	 * 获取绘图时应绘制的位置
	 * 
	 * @return 绘图时应绘制的位置
	 */
	public Vector2DF getDrawPosition() {
		Vector2DF sc = getDisplayAreaFixScaleForPosition();
		if(getParent() instanceof GameRootObject)
		return getRoot().transitionPosition(getPosition()).scale(sc.getX(), sc.getY());
		else return getPosition().scaleNew(sc.getX(), sc.getY());
	}

	/**
	 * 获取绘图时应绘制的位置偏移量
	 * 
	 * @return 绘图时应绘制的位置偏移量
	 */
	public Vector2DF getDrawPositionOffset() {
		Vector2DF sc = getDisplayAreaFixScaleForPosition();
		return getPositionOffset().scaleNew(sc.getX(), sc.getY());
	}

	/**
	 * 获取绘图时应绘制的矩形区域
	 * 
	 * @return 绘图时应绘制的矩形区域
	 */
	public RectF getDrawRectF() {
		Vector2DF s = getDrawPosition().plusNew(getDrawPositionOffset());
		Vector2DF e = s.plusNew(getDrawSize());
		return new RectF(s.getX(), s.getY(), e.getX(), e.getY());
	}

	/**
	 * 获取原始矩形区域，该矩形仅为位置、偏移量与尺寸的总和
	 * 
	 * @return 原始矩形区域
	 */
	public RectF getRectF() {
		Vector2DF s = getPosition().plusNew(getPositionOffset());
		Vector2DF e = s.plusNew(getSize());
		return new RectF(s.getX(), s.getY(), e.getX(), e.getY());
	}

	/**
	 * 根据当前对象的属性，重置原点、改变画布方向和缩放比例
	 */
	protected void operateCanvas(Canvas c) {
		Vector2DF p = getDrawPosition();
		Vector2DF o = getDrawPositionOffset();

		c.translate(p.getX(), p.getY());
		
		clipCanvas(c, o);
		
		c.rotate(getRotation());
		
		Vector2DF sc = getScale();
		c.scale(sc.getX(), sc.getY());
		operateCanvasForParentAbsoluteSize(c);

		c.translate(o.getX(), o.getY());
		
	}
	
	/**
	 * 获取当前层次绘图的变换矩阵，该矩阵与当前层次的Canvas变换矩阵相等
	 */
	public Matrix getMatrix(){
		GameObject pa = getParent();
		Matrix m = pa==null?new Matrix():pa.getMatrix();
		
		Vector2DF p = getDrawPosition();
		Vector2DF o = getDrawPositionOffset();
		m.preTranslate(p.getX(), p.getY());
		
		m.preRotate(getRotation());
		
		Vector2DF sc = getScale();
		m.preScale(sc.getX(),sc.getY());
		operateMatrixForParentAbsoluteSize(m);
		
		m.preTranslate(o.getX(), o.getY());
		
		return m;
	}

	/**
	 * 剪裁画布，默认不剪裁，如需剪裁可重写此方法
	 * 
	 * @param c
	 *            画布
	 * @param offset
	 *            参考偏移量
	 */
	protected void clipCanvas(Canvas c, Vector2DF offset) {
		// if (this instanceof GameLeafObject) {
		// c.clipRect(new VectorRect2DF(getDrawPositionOffset(),
		// getDrawSize()).getRectF());
		// }
	}

	/**
	 * 针对父级设定的固定尺寸，对画布进行缩放，以使子控件填充
	 * 
	 * @param c
	 *            画布
	 */
	protected void operateCanvasForParentAbsoluteSize(Canvas c) {
		Vector2DF s = getParentAbsoluteSizeScale();
		c.scale(s.getX(), s.getY());
	}
	
	/**
	 * 针对父级设定的固定尺寸，对矩阵进行缩放，以使子控件填充
	 * 
	 * @param c
	 *            画布
	 */
	protected void operateMatrixForParentAbsoluteSize(Matrix m) {
		Vector2DF s = getParentAbsoluteSizeScale();
		m.preScale(s.getX(), s.getY());
	}
	
	/**
	 * 获取匹配到父级的绝对尺寸影响所需的缩放值。
	 */
	protected Vector2DF getParentAbsoluteSizeScale(){
		if (getParent() != null&&!(getParent() instanceof GameSpiritGroup)) {
			float xs = getParent().getDrawWidth() / getDrawWidth();
			float ys = getParent().getDrawHeight() / getDrawHeight();
			if (getParent().getIsStretchContent()) {
				return new Vector2DF(xs, ys);
			} else {
				float as = Math.min(xs, ys);
				return new Vector2DF(as, as);
			}
		}
		return new Vector2DF(1, 1);
	}

	/**
	 * 绘制
	 * 
	 * @param c
	 *            画板
	 * @param drawArea
	 *            绘图参考区域
	 */
	protected abstract void drawSelf(Canvas c, Rect drawArea);

	/**
	 * 绘所有制子对象
	 * 
	 * @param c
	 *            画板
	 * @param drawArea
	 *            绘图参考区域
	 */
	protected abstract void drawChilds(Canvas c, Rect drawArea);
	
	/**
	 * 绘制子对象，子类在绘制子对象时应当调用此方法，而不是直接执行子类的绘制方法，以实现更好的控制
	 * @param child 子对象
	 * @param c 画板
	 * @param drawArea 绘图参考区域
	 */
	protected final void drawChild(GameObject child,Canvas c, Rect drawArea)
	{
		if(onDrawingChild(child, c, drawArea)){
			child.draw(c, drawArea);
		}			
		onDrawingChild(child, c, drawArea);
	}
	
	/**
	 * 在drawChild方法中，绘制子对象前触发，子类可以通过重写此方法实现自定行为，可通过返回false阻止此次绘制
	 * @param child 子对象
	 * @param c 画板
	 * @param drawArea 绘图参考区域
	 */
	protected boolean onDrawingChild(GameObject child,Canvas c, Rect drawArea)
	{
		return true;
	}
	
	/**
	 * 在drawChild方法中，绘制子对象后触发，子类可以通过重写此方法实现自定行为
	 * @param child 子对象
	 * @param c 画板
	 * @param drawArea 绘图参考区域
	 */
	protected void onDrawnChild(GameObject child,Canvas c, Rect drawArea)
	{
		
	}

	/**
	 * 更新操作
	 */
	public void update() {
		if (onUpdating()) {
			updateSelf();
			getMotionGroup().update(this);
			updateChilds();
		}
		onUpdated();
	}

	/**
	 * 更新自身
	 */
	protected abstract void updateSelf();

	/**
	 * 更新子对象
	 */
	protected abstract void updateChilds();

	/**
	 * 当开始更新时触发，监听器返回false可阻止此次更新
	 */
	public interface OnUpdatingListener {
		/**
		 * 触发Updating事件时执行的方法。事件功能注释：当开始更新时触发，监听器返回false可阻止此次更新
		 * 
		 * @param sender
		 *            触发Updating事件的对象
		 */
		public abstract boolean OnUpdatingEvent(Object sender);
	}

	/**
	 * Updating事件监听器列表。当开始更新时触发，监听器返回false可阻止此次更新
	 */
	private ArrayList<OnUpdatingListener> _UpdatingListenerList = null;

	/**
	 * 增加一个Updating事件的监听器，返回是否成功增加。事件功能注释：当开始更新时触发，监听器返回false可阻止此次更新
	 * 
	 * @param listener
	 *            Updating事件监听器对象
	 * @return 是否成功增加。如果该监听器对象已存在，则返回false。
	 */
	public boolean addOnUpdatingListener(OnUpdatingListener listener) {
		if (_UpdatingListenerList == null)
			_UpdatingListenerList = new ArrayList<OnUpdatingListener>();
		else if (_UpdatingListenerList.contains(listener))
			return false;
		_UpdatingListenerList.add(listener);
		return true;
	}

	/**
	 * 移除一个Updating事件的监听器，返回是否成移除。事件功能注释：当开始更新时触发，监听器返回false可阻止此次更新
	 * 
	 * @param listener
	 *            Updating事件监听器对象
	 * @return 是否成功移除。如果该监听器对象不存在，则返回false。
	 */
	public boolean removeOnUpdatingListener(OnUpdatingListener listener) {
		if (_UpdatingListenerList == null
				|| !_UpdatingListenerList.contains(listener))
			return false;
		_UpdatingListenerList.remove(listener);
		return true;
	}

	/**
	 * 清空所有Updating事件的监听器。事件功能注释：当开始更新时触发，监听器返回false可阻止此次更新
	 */
	public void clearOnUpdatingListeners() {
		if (_UpdatingListenerList != null)
			_UpdatingListenerList.clear();
	}

	/**
	 * 当开始更新时触发，监听器返回false可阻止此次更新
	 */
	protected boolean onUpdating() {
		if (_UpdatingListenerList != null)
			for (OnUpdatingListener listener : _UpdatingListenerList) {
				if (!listener.OnUpdatingEvent(this))
					return false;
			}
		return true;
	}

	/**
	 * 当更新结束时触发
	 */
	public interface OnUpdatedListener {
		/**
		 * 触发Updated事件时执行的方法。事件功能注释：当更新结束时触发
		 * 
		 * @param sender
		 *            触发Updated事件的对象
		 */
		public abstract void OnUpdatedEvent(Object sender);
	}

	/**
	 * Updated事件监听器列表。当更新结束时触发
	 */
	private ArrayList<OnUpdatedListener> _UpdatedListenerList = null;

	/**
	 * 增加一个Updated事件的监听器，返回是否成功增加。事件功能注释：当更新结束时触发
	 * 
	 * @param listener
	 *            Updated事件监听器对象
	 * @return 是否成功增加。如果该监听器对象已存在，则返回false。
	 */
	public boolean addOnUpdatedListener(OnUpdatedListener listener) {
		if (_UpdatedListenerList == null)
			_UpdatedListenerList = new ArrayList<OnUpdatedListener>();
		else if (_UpdatedListenerList.contains(listener))
			return false;
		_UpdatedListenerList.add(listener);
		return true;
	}

	/**
	 * 移除一个Updated事件的监听器，返回是否成移除。事件功能注释：当更新结束时触发
	 * 
	 * @param listener
	 *            Updated事件监听器对象
	 * @return 是否成功移除。如果该监听器对象不存在，则返回false。
	 */
	public boolean removeOnUpdatedListener(OnUpdatedListener listener) {
		if (_UpdatedListenerList == null
				|| !_UpdatedListenerList.contains(listener))
			return false;
		_UpdatedListenerList.remove(listener);
		return true;
	}

	/**
	 * 清空所有Updated事件的监听器。事件功能注释：当更新结束时触发
	 */
	public void clearOnUpdatedListeners() {
		if (_UpdatedListenerList != null)
			_UpdatedListenerList.clear();
	}

	/**
	 * 当更新结束时触发
	 */
	protected void onUpdated() {
		if (_UpdatedListenerList != null)
			for (OnUpdatedListener listener : _UpdatedListenerList) {
				listener.OnUpdatedEvent(this);
			}
	}

	/**
	 * 当开始更新绘制时触发，监听器返回false可阻止此次绘制
	 */
	public interface OnDrawingListener {
		/**
		 * 触发Drawing事件时执行的方法。事件功能注释：当开始更新绘制时触发，监听器返回false可阻止此次绘制
		 * 
		 * @param sender
		 *            触发Drawing事件的对象
		 */
		public abstract boolean OnDrawingEvent(Object sender, Canvas c,
				Rect drawArea);
	}

	/**
	 * Drawing事件监听器列表。当开始更新绘制时触发，监听器返回false可阻止此次绘制
	 */
	private ArrayList<OnDrawingListener> _DrawingListenerList = null;

	/**
	 * 增加一个Drawing事件的监听器，返回是否成功增加。事件功能注释：当开始更新绘制时触发，监听器返回false可阻止此次绘制
	 * 
	 * @param listener
	 *            Drawing事件监听器对象
	 * @return 是否成功增加。如果该监听器对象已存在，则返回false。
	 */
	public boolean addOnDrawingListener(OnDrawingListener listener) {
		if (_DrawingListenerList == null)
			_DrawingListenerList = new ArrayList<OnDrawingListener>();
		else if (_DrawingListenerList.contains(listener))
			return false;
		_DrawingListenerList.add(listener);
		return true;
	}

	/**
	 * 移除一个Drawing事件的监听器，返回是否成移除。事件功能注释：当开始更新绘制时触发，监听器返回false可阻止此次绘制
	 * 
	 * @param listener
	 *            Drawing事件监听器对象
	 * @return 是否成功移除。如果该监听器对象不存在，则返回false。
	 */
	public boolean removeOnDrawingListener(OnDrawingListener listener) {
		if (_DrawingListenerList == null
				|| !_DrawingListenerList.contains(listener))
			return false;
		_DrawingListenerList.remove(listener);
		return true;
	}

	/**
	 * 清空所有Drawing事件的监听器。事件功能注释：当开始更新绘制时触发，监听器返回false可阻止此次绘制
	 */
	public void clearOnDrawingListeners() {
		if (_DrawingListenerList != null)
			_DrawingListenerList.clear();
	}

	/**
	 * 当开始更新绘制时触发，监听器返回false可阻止此次绘制
	 */
	protected boolean onDrawing(Canvas c, Rect drawArea) {
		if (_DrawingListenerList != null)
			for (OnDrawingListener listener : _DrawingListenerList) {
				if (!listener.OnDrawingEvent(this, c, drawArea))
					return false;
			}
		return true;
	}

	/**
	 * 当绘制结束时触发
	 */
	public interface OnDrawnListener {
		/**
		 * 触发Drawn事件时执行的方法。事件功能注释：当绘制结束时触发
		 * 
		 * @param sender
		 *            触发Drawn事件的对象
		 */
		public abstract void OnDrawnEvent(Object sender, Canvas c, Rect drawArea);
	}

	/**
	 * Drawn事件监听器列表。当绘制结束时触发
	 */
	private ArrayList<OnDrawnListener> _DrawnListenerList = null;

	/**
	 * 增加一个Drawn事件的监听器，返回是否成功增加。事件功能注释：当绘制结束时触发
	 * 
	 * @param listener
	 *            Drawn事件监听器对象
	 * @return 是否成功增加。如果该监听器对象已存在，则返回false。
	 */
	public boolean addOnDrawnListener(OnDrawnListener listener) {
		if (_DrawnListenerList == null)
			_DrawnListenerList = new ArrayList<OnDrawnListener>();
		else if (_DrawnListenerList.contains(listener))
			return false;
		_DrawnListenerList.add(listener);
		return true;
	}

	/**
	 * 移除一个Drawn事件的监听器，返回是否成移除。事件功能注释：当绘制结束时触发
	 * 
	 * @param listener
	 *            Drawn事件监听器对象
	 * @return 是否成功移除。如果该监听器对象不存在，则返回false。
	 */
	public boolean removeOnDrawnListener(OnDrawnListener listener) {
		if (_DrawnListenerList == null
				|| !_DrawnListenerList.contains(listener))
			return false;
		_DrawnListenerList.remove(listener);
		return true;
	}

	/**
	 * 清空所有Drawn事件的监听器。事件功能注释：当绘制结束时触发
	 */
	public void clearOnDrawnListeners() {
		if (_DrawnListenerList != null)
			_DrawnListenerList.clear();
	}

	/**
	 * 当绘制结束时触发
	 */
	protected void onDrawn(Canvas c, Rect drawArea) {
		if (_DrawnListenerList != null)
			for (OnDrawnListener listener : _DrawnListenerList) {
				listener.OnDrawnEvent(this, c, drawArea);
			}
	}

	/**
	 * 初始值为new GameMotionGroup()。 功能注释：应用的变化组，启动后将随对象而更新
	 */
	private GameMotionGroup _MotionGroup = new GameMotionGroup();

	/**
	 * 获取MotionGroup。 功能注释：应用的变化组，启动后将随对象而更新
	 * 
	 * @return 当前的GameMotionGroup类型的值
	 */
	public GameMotionGroup getMotionGroup() {
		return _MotionGroup;
	}

	/**
	 * 设置MotionGroup。 功能注释：应用的变化组，启动后将随对象而更新
	 * 
	 * @param value
	 *            要设置的GameMotionGroup类型值
	 */
	protected void setMotionGroup(GameMotionGroup value) {
		_MotionGroup = value;
	}

	/**
	 * 设置MotionGroup为其默认值(new GameMotionGroup())。 功能注释：应用的变化组，启动后将随对象而更新
	 */
	protected void setMotionGroupToDefault() {
		setMotionGroup(new GameMotionGroup());
	}

	/**
	 * 获取Root。 功能注释：获取根节点对象
	 * 
	 * @return 当前的GameRootObject类型的值
	 */
	public GameRootObject getRoot() {
		return getParent().getRoot();
	}
	
//	/**
//	 * 对点进行缩放、旋转等变化
//	 * @param AngularPoint 点
//	 * @param Center 旋转、缩放的中心点
//	 * @return 变化后的角点位置
//	 */
//	protected Vector2DF operatePoint(Vector2DF AngularPoint,Vector2DF Center){
//		return AngularPoint.scale(_Scale,Center).scale(getParentAbsoluteSizeScale(),Center).rotate(_Rotation, Center);
//	}
	
//	/**
//	 * 获取中心点位置，默认返回Position属性的副本
//	 */
//	public Vector2DF getCenterPoint(){
//		return _Position.getClone();
//	}
//	
//	/**
//	 * 获取经过层级叠加后的真实中心点显示位置
//	 */
//	public Vector2DF getRealDisplayCenterPoint(){
//		if(getParent()!=null)return getParent().getRealDisplayCenterPoint().plus(getCenterPoint());
//		return getCenterPoint();
//	}
	
	/**
	 * 获取左上方的角点A，该值是未经缩放、旋转等变化的原始值
	 */
	public Vector2DF getAngularPointA(){
		return new Vector2DF(0, 0);
	}
	
//	public Vector2DF getDisplayBasePosition(){
//		GameObject p = getParent();
//		Vector2DF v = operatePoint(getAngularPointA(), getCenterPoint());
//		return p==null?v:v.plus(p.getDisplayBasePosition());
//	}
//	
//	public Vector2DF getDisplayCenterPoint(){
//		GameObject p = getParent();
//		return p==null?getCenterPoint():p.combinationAngularPoint(getCenterPoint());
//	}
	
	/**
	 * 获取右下方的角点A，该值是经过缩放、旋转等变化后的值
	 * @param m 映射矩阵
	 */
	public Vector2DF getDisplayAngularPointA(Matrix m){
		return getRoot().transitionPosition(getAngularPointA().map(m));
	}
	
	/**
	 * 获取右下方的角点A，该值是经过缩放、旋转等变化后的值
	 */
	public Vector2DF getDisplayAngularPointA(){
		return getDisplayAngularPointA(getMatrix());
	}
	
//	protected Vector2DF combinationAngularPoint(Vector2DF subAngularPoint) {
//		Vector2DF v = operatePoint(subAngularPoint.plus(getAngularPointA()), getCenterPoint());
//		GameObject p = getParent();	
//		return p==null?v:p.combinationAngularPoint(v);
//	}
	
	/**
	 * 获取右上方的角点B，该值是未经缩放、旋转等变化的原始值
	 */
	public Vector2DF getAngularPointB(){
		return getAngularPointA().plus(getDrawSize().scaleNew(1,0));
	}
	
	/**
	 * 获取右下方的角点B，该值是经过缩放、旋转等变化后的值
	 * @param m 映射矩阵
	 */
	public Vector2DF getDisplayAngularPointB(Matrix m){
		return getRoot().transitionPosition(getAngularPointB().map(m));
	}
	
	/**
	 * 获取右下方的角点B，该值是经过缩放、旋转等变化后的值
	 */
	public Vector2DF getDisplayAngularPointB(){
		return getDisplayAngularPointB(getMatrix());
	}
	
	/**
	 * 获取左下方的角点C，该值是未经缩放、旋转等变化的原始值
	 */
	public Vector2DF getAngularPointC(){
		return getAngularPointA().plus(getDrawSize().scaleNew(0,1));
	}
	
	/**
	 * 获取右下方的角点C，该值是经过缩放、旋转等变化后的值
	 * @param m 映射矩阵
	 */
	public Vector2DF getDisplayAngularPointC(Matrix m){
		return getRoot().transitionPosition(getAngularPointC().map(m));
	}
	
	/**
	 * 获取右下方的角点C，该值是经过缩放、旋转等变化后的值
	 */
	public Vector2DF getDisplayAngularPointC(){
		return getDisplayAngularPointC(getMatrix());
	}
	
	/**
	 * 获取右下方的角点D，该值是未经缩放、旋转等变化的原始值
	 */
	public Vector2DF getAngularPointD(){
		return getAngularPointA().plus(getDrawSize());
	}
	
	/**
	 * 获取右下方的角点D，该值是经过缩放、旋转等变化后的值
	 * @param m 映射矩阵
	 */
	public Vector2DF getDisplayAngularPointD(Matrix m){
		return getRoot().transitionPosition( getAngularPointD().map(m));
	}
	
	/**
	 * 获取右下方的角点D，该值是经过缩放、旋转等变化后的值
	 */
	public Vector2DF getDisplayAngularPointD(){
		return getDisplayAngularPointD(getMatrix());
	}
	
	/**
	 * 将位置偏移量设为尺寸的一半，使得中心点居于对象正中
	 */
	public void setPositionOffsetToHalfSize(){
		getPositionOffset().resetWith(getSize().scaleNew(0.5f).negate());
	}
	
	/**
	 * 检测传入位置是否位于此对象的可视区域内。通常用于点击检测。
	 * @param pos
	 * @return
	 */
	public boolean checkIsInViewArea(Vector2DF pos){
		return pos.isIn(getDisplayRectF());
	}
}
